package com.googlecode.uipipedream.impl;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;

import com.googlecode.uipipedream.spec.ColourModel;
import com.googlecode.uipipedream.spec.HSBType;
import com.googlecode.uipipedream.spec.SliderBar;

/**
 * @author <a href="http://daemonsadvocate.blogspot.com/">Matthew B. Gray</a>
 */
public class HorizontalSliderBar extends SliderBar {
	private static final long serialVersionUID = 4988289504165404166L;
	private Rectangle boundingBox;
	private ColourModel model;
	private boolean draggingBox = false;
	private HSBType type;
	private Dimension cachedCanvasSize;
	private Image drawing;
	private Graphics graphics = null;
	
	public HorizontalSliderBar(ColourModel model, HSBType type) {
		super(model);
		this.model = model;
		this.type = type;
	}
	
	@Override public Dimension preferredSize() { return new Dimension(500, 80); }
	@Override public Dimension minimumSize() { return new Dimension(500, 80); }
	
	public synchronized void paint(Graphics g) {
		// 0. Cache dimensions and setup object.
		Dimension d = getSize();
		if ((graphics == null) || (d.width != cachedCanvasSize.width) || (d.height != cachedCanvasSize.height)) {
			cachedCanvasSize = d;
			this.drawing = createImage(d.width, d.height);
			graphics = this.drawing.getGraphics();
			// border of 4 all round, 8 at left
			boundingBox = new Rectangle(4, 4, d.width - 4, d.height - 4);
		}

		// 1. Erase the previous image.
		graphics.setColor(getBackground());
		graphics.fillRect(0, 0, d.width, d.height);
		graphics.setColor(Color.black);

		// 2. Paint the brightness bar
		for (int i=0; i<boundingBox.width; ++i) {
			float offset = 1f - (float) i / boundingBox.width;
			graphics.setColor(Color.getHSBColor(offset, model.getSaturation(), model.getBrightness()));
			graphics.drawLine(boundingBox.x + i, boundingBox.y, boundingBox.x +i, boundingBox.y + boundingBox.height - 1);
		}
		graphics.setColor(Color.white);
		graphics.drawRect(boundingBox.x, boundingBox.y, boundingBox.width-1, boundingBox.height-1);

		// 3. Paint main colour selection box.
		float offset = model.getHue();
		int selectorWidth = (int) (this.getBounds().width * 0.08);
		int selectorHeight = (int) (this.getBounds().height * );
		int selectorX = offset - selectorWidth / 2;
		int selectorY = offset - 
		int xx = boundingBox.y + (int) (boundingBox.width * (1.0 - offset));
		graphics.drawRect(x, y, width, height)(xx, boundingBox.y, xx, boundingBox.y + boundingBox.width - 1);
//		graphics.drawLine(xx, boundingBox.y - 2, xx + 3, boundingBox.y - 7);
//		graphics.drawLine(xx, boundingBox.y - 2, xx - 3, boundingBox.y - 7);
//		graphics.drawLine(xx, boundingBox.y - 7, xx + 3, boundingBox.y - 7);

		g.drawImage(drawing, 0, 0, this);
	}

	public boolean mouseDrag(Event e, int x, int y) {
		if (draggingBox) {
			float offset = 1f - (float) (x - boundingBox.x) / boundingBox.width;
			if (offset < 0) offset = 0f;
			if (offset > 1f) offset = 1f;
			
			switch (type) {
			case HUE:
				model.setHue(offset);
				break;
			case SATURATION:
				model.setSaturation(offset);
				break;
			case BRIGHTNESS:
				model.setBrightness(offset);
				break;
			}
			return true;
		}
		return false;
	}

	public boolean mouseDown(Event e, int x, int y) {
		draggingBox = false;

		if (boundingBox.contains(x, y)) {
			draggingBox = true;
			float offset = 1f - (float) (x - boundingBox.x) / boundingBox.width;
			switch (type) {
			case HUE:
				model.setHue(offset);
				break;
			case SATURATION:
				model.setSaturation(offset);
				break;
			case BRIGHTNESS:
				model.setBrightness(offset);
				break;
			}
			return true;
		}
		
		float curr = 0;
		switch (type) {
		case HUE:
			curr = model.getHue();
			break;
		case SATURATION:
			curr = model.getSaturation();
			break;
		case BRIGHTNESS:
			curr = model.getBrightness();
			break;
		}
		
		int dx = x - boundingBox.x - (int) (boundingBox.width * (1f - curr));
		if (y < boundingBox.y && y >= boundingBox.y - 8 && dx >= -4 && dx <= 4) {
			draggingBox = true;
			return true;
		}
		return false;
	}
}
